#include <iostream>
#include <string>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#define MAXLINE 4096

using namespace std;

int main(int argc, char **argv)
{
    int listenfd, acceptfd;
    struct sockaddr_in servaddr;
    //绑定端口和准备收包
    // 根据地址类型创建了一个TCP的socket，如果出错打印出错码
    // socket参数：(协议域如ipv4，socket类型如tcp，指定协议若0时自动选择)
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        cout << "create socket error:" << strerror(errno) << "(errno:" << errno << ")" << endl;
        return -1;
    }
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    // INADDR_ANY一般指定系统中的0.0.0.0地址
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(6666);
    // 将地址绑定在listenfd上
    // bind参数：(socket描述字，一个const struct sockaddr*指针指向要绑定socketfd的协议地址)
    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        cout << "bind socket error:" << strerror(errno) << "(errno:" << errno << ")" << endl;
        return -1;
    }
    // 监听这个listenfd，若客户端调用connect()发出请求，服务器端就会收到
    // listen参数：(要监听的socket描述字，相应socket可以排队的最大连接个数)
    if (listen(listenfd, 10) == -1)
    {
        cout << "listen socket error:" << strerror(errno) << "(errno:" << errno << ")" << endl;
        return -1;
    }
    cout << "======waiting for client's request======" << endl;
    // 在while循环中持续接收包，accpet和recv都在循环中，即收到包后fd关闭，下个包重新接收包
    // TCP服务器监听到请求后，调用accept()函数，连接就建立好了
    // accpet参数：(服务器socket描述字，指向struct sockaddr*的指针用于返回客户端的协议地址，协议地址长度)
    // 若accpet成功，返回值是由内核自动生成的一个全新的描述字，代表与返回客户的TCP连接
    // accpet的第一个参数是服务器的监听socket描述字，只创建一个
    // accept函数返回的是已连接的socket描述字，内核为每个由服务器进程接受的客户创建了一个已连接的socket描述字，当服务器完成服务，相应的已连接socket描述字就被关闭
    if ((acceptfd = accept(listenfd, (struct sockaddr *)NULL, NULL)) == -1)
    {
        cout << "accept socket error:" << strerror(errno) << "(errno:" << errno << ")" << endl;
    }

    // 先收100个字节
    char recvMsg[100];
    ssize_t readLen = read(acceptfd, recvMsg, sizeof(recvMsg));
    if (readLen < 0)
    {
        cout << "read error: " << strerror(errno) << "(errno:" << errno << ")" << endl;
        return -1;
    }
    recvMsg[9] = '\0';
    cout << "readlen: " << readLen << ", recvMsg: " << recvMsg << endl;
    // 休眠5s（失败）
    sleep(5);
    // 休眠1s（成功）
    // sleep(1);
    // 把收到的字符串中的第二个字节改为9
    recvMsg[1] = '9';
    // 把新字符串发出去
    ssize_t writeLen = write(acceptfd, recvMsg, sizeof(recvMsg));
    cout << "writeLen: " << writeLen << ", sendMsg: " << recvMsg << endl;
    if (writeLen < 0)
    {
        cout << "writeLen error: " << strerror(errno) << "(errno:" << errno << ")" << endl;
        return -1;
    }
    // 客户端给服务端发送了一个请求，服务端休眠5s之后再给客户端回包，因为客户端超时时间为2s，所以客户端收包失败
    close(acceptfd);
    return 0;
}
